#include <iostream>
#include <cstdint>

class A {
private:
	int data1_;
	int data2_;

public:
	A() {
		data1_ = 1;
		data2_ = 1;
		std::cout << "A::A()" << std::endl;
	};

	virtual ~A() {
		std::cout << "A::~A()" << std::endl;
	}

public:
	virtual void vAfunc1() {
		std::cout << "A::vAfunc1()" << std::endl;
	}

	virtual void vAfunc2() {
		std::cout << "A::vAfunc2()" << std::endl;
	}

public:
	void func1() {
		std::cout << "A::func1()" << std::endl;
	}

	void func2() {
		std::cout << "A::func2()" << std::endl;
	}
};

class B : public A {
private:
	int data3_{};

public:
	B() {
		data3_ = 3;
		std::cout << "B::B()" << std::endl;
	};

	virtual ~B() {
		std::cout << "B::~B()" << std::endl;
	}

public:
	virtual void vBfunc1() {
		std::cout << "B::vBfunc1()" << std::endl;
	}

	virtual void vBfunc2() {
		std::cout << "B::vBfunc2()" << std::endl;
	}

	virtual void vAfunc1() override {
		std::cout << "B::vAfunc1()" << std::endl;
	}

public:
	void func1() {
		std::cout << "B::func1()" << std::endl;
	}

	void func2() {
		std::cout << "B::func2()" << std::endl;
	}
};

using VoidFuncPtr = void(*)();


void FuncRTTI(A* a) {
	if (typeid(*a) == typeid(A))
		a->func1();

	else if (typeid(*a) == typeid(B)) {
		B* b = reinterpret_cast<B*>(a);
		b->func1();
	}
}

int main() {
	B b;

	int64_t* pvtbl = (int64_t*)&b;
	std::cout << "b 的地址(虚指针的地址): " << pvtbl << std::endl;

	int64_t* pvAfunc1 = (int64_t*)*pvtbl;
	std::cout << "虚指针的指向(虚表的地址): " << (int64_t*)*pvtbl << std::endl;

	pvAfunc1++;	//g++ 越过 typeinfo

	// g++	越过 ~B
	pvAfunc1++;

	//B::vAfunc1
	VoidFuncPtr vAfunc1 = (VoidFuncPtr)*pvAfunc1;
	(*vAfunc1)();

	std::cout << "b 中 vAfunc1 的地址为: " << (int64_t*)*pvAfunc1 << std::endl;

	pvAfunc1++;
	//A::vAfunc2
	vAfunc1 = (VoidFuncPtr)*pvAfunc1;
	(*vAfunc1)();

	pvAfunc1++;
	//B::vBfunc1
	vAfunc1 = (VoidFuncPtr)*pvAfunc1;
	(*vAfunc1)();

	pvAfunc1++;
	//B::vBfunc2
	vAfunc1 = (VoidFuncPtr)*pvAfunc1;
	(*vAfunc1)();


	B b1;
	std::cout << "b1 中 vAfunc1 的地址为: " << (int64_t*)(* ( (int64_t*)(*(int64_t*)&b1) + 1 ) ) << std::endl;
	//VoidFuncPtr vAfunc1_0 = (VoidFuncPtr)*pvAfunc1;

	A a;
	std::cout << "a 中 vAfunc1 的地址为: " << (int64_t*)(* ( (int64_t*)(*(int64_t*)&a) + 1 ) ) << std::endl;

	A a1 = b1;
	std::cout << "a1 中 vAfunc1 的地址为: " << (int64_t*)( * ( (int64_t*)(*(int64_t*)&a1) + 1 ) ) << std::endl;
	a1.vAfunc1();

	A* pa = &b1;
	std::cout << "a1 中 vAfunc1 的地址为: " << (int64_t*) ( * ( (int64_t*)(*(int64_t*)&(*pa)) + 1) )<< std::endl;
	pa->vAfunc1();

	std::cout << "A 虚表地址为: " << (int64_t*)(*(int64_t*)&a) << std::endl;

	std::type_info* typeInfoA = (std::type_info*)( * ( (int64_t*)(*(int64_t*)&a) - 1 ) );
	std::cout << "typeinfoA 地址: " << ", " << typeInfoA << std::endl;
	std::cout << typeInfoA->name() << std::endl;	//error in MSVC

	const std::type_info& _typeInfoA = typeid(a);
	std::cout << "_typeinfoA 地址: " << ", " << &_typeInfoA << std::endl;
	std::cout << _typeInfoA.name() << std::endl;

	const std::type_info& _typeInfoClassA = typeid(A);
	std::cout << "_typeInfoClassA 地址: " << ", " << &_typeInfoClassA << std::endl;
	std::cout << _typeInfoClassA.name() << std::endl;

	std::cout << bool{ _typeInfoA == _typeInfoClassA } << std::endl;


	FuncRTTI(&a);
	FuncRTTI(&b);


	A da;
	B db;

	A* pda = dynamic_cast<A*>(&db);
	B* pdb = dynamic_cast<B*>(pda);

	B* pdba = dynamic_cast<B*>(&da);

	return 0;
}